﻿using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;

namespace pallete_main
{
    //设备结构体
    public struct _port{
        //连接设备的路由端口
        public string port_name;
        //设备名称,如果没有链接
        //设备名称是null
        public string name;
    }

    //路由结构体
    public struct _router {
        //路由名称
        public string name;
        //_port 列表
        public ArrayList list_port;
    } 

    //设备坐标信息结构体
    public struct _device_item{
        public Point2d pt;
        public string name;
        //连接端口在列表中的
        //索引
        public int index;
    }

    //端口坐标信息结构体
    public struct _port_item
    {
        public Point2d pt;
        public string name;
    }

    //路由坐标信息结构体
    public struct _router_item{
        //当前交换机的起始位置,左上为坐标原点
        public Point2d m_ptOffset;
        //当前路由名称
        public string m_nameRouter;
        //上方的端口列表,_prot_item
        public ArrayList m_lstPort1;
        //下方的端口列表,_prot_item
        public ArrayList m_lstPort2;
    }

    class module_zuwang
    {
        //Polyline list,交换机，上层设备间连线列表
        private ArrayList m_lstPolyline1 = new ArrayList();
        //Polyline list,交换机，下层设备间连线列表
        private ArrayList m_lstPolyline2 = new ArrayList();
        //交换机上方设备列表
        private ArrayList m_lstDevice1 = new ArrayList();
        //交换机下方设备列表
        private ArrayList m_lstDevice2 = new ArrayList();
        //当前路由设备
        private _router_item m_router;
        //设备间距
        private int m_disDevice = 20;
        //设备和交换机间距
        private int m_disDeviceRouter = 50;
        //连线之间y坐标间距
        private int m_disLine = 5;
        //设备模块的长宽
        private int m_nDeviceWidth = 30;
        private int m_nDeviceHeight = 20;
        //路由长宽
        private int m_nRouterWidth = 200;
        private int m_nRouterHeight = 50;
        //字体大小
        private int m_fontSize = 2;
        //不同交换机设备图之间的距离
        private int m_disRouter = 100;
        //整个表格的偏移位置
        private Point3d m_pOffset = new Point3d(100, 300,0);
        //路由设备端口，圆形的半径
        private int m_nRadio = 10;

        //计算单个路由设备所有信息由设备
        private void DrawRouter()
        {
        }

        //计算单个router布局
        private void CalLayout(_router router)
        {
            //当前路由图象对于第一福路由图的偏移位置
            Point2d ptOffset;// = m_router.m_ptOffset;
            int nDeviceCount = 0;

            int nPortNum = router.list_port.Count;
            //端口号之间的距离 
            int nDisPort = 0;
            if (nPortNum <= 0)
            {
                MessageBox.Show("路由设备端口号错误！");
                return;
            }

            //每边一半端口
            nDisPort = m_nRouterWidth / (nPortNum/2 + 1);

            ptOffset = m_router.m_ptOffset + new Vector2d(0,-m_nRadio);
            //计算路由上端口的位置
            for (int i = 0; i < nPortNum / 2; i++)
            {
                _port port = (_port)router.list_port[i];
                ptOffset += new Vector2d(nDisPort,0);
                _port_item item = new _port_item();
                item.pt = ptOffset;
                item.name = port.port_name;

                m_router.m_lstPort1.Add(item);

                //有效表示，该口连接一个设备
                if (port.name != null)
                {
                    _device_item temp_item = new _device_item();
                    //首个设备
                    if(m_lstDevice1.Count == 0)
                    {
                        temp_item.pt = new Point2d(ptOffset.X - m_nDeviceWidth/2, m_disDeviceRouter + m_nDeviceHeight);
                    }
                    else
                    {
                        nDeviceCount = m_lstDevice1.Count;
                        _device_item last_item = (_device_item)m_lstDevice1[nDeviceCount - 1];
                        temp_item.pt = last_item.pt + new Vector2d (m_disDevice + m_nDeviceWidth,0);
                    }
                    temp_item.index = i;
                    temp_item.name = port.name;
                    m_lstDevice1.Add(temp_item);
                }
            }

            //计算路由下端口的位置
            ptOffset = m_router.m_ptOffset + new Vector2d(0,-m_nRouterHeight + m_nRadio);
            for (int i =  (nPortNum/2); i <  nPortNum; i++)
            {
                _port port = (_port)router.list_port[i];
                ptOffset += new Vector2d(nDisPort,0);
                _port_item item = new _port_item();
                item.pt = ptOffset;
                item.name = port.port_name;

                m_router.m_lstPort2.Add(item);

                //有效表示，该口连接一个设备
                if (port.name != null)
                {
                    _device_item temp_item = new _device_item();
                    //首个设备
                    if(m_lstDevice2.Count == 0)
                    {
                        temp_item.pt = new Point2d(ptOffset.X - m_nDeviceWidth/2, -m_disDeviceRouter - m_nRouterHeight);
                    }
                    else
                    {
                        nDeviceCount = m_lstDevice2.Count;
                        _device_item last_item = (_device_item)m_lstDevice2[nDeviceCount - 1];
                        temp_item.pt = last_item.pt + new Vector2d(m_disDevice + m_nDeviceWidth, 0);
                    }

                    temp_item.index = i - nPortNum/2;
                    temp_item.name = port.name;
                    m_lstDevice2.Add(temp_item);
                }
            }


            //计算交换机上方连线的位置
            nDeviceCount = m_lstDevice1.Count;
            for (int i = 0; i < nDeviceCount; i++)
            {
                _device_item device = (_device_item)m_lstDevice1[i];
                Point2d ptDevice = device.pt;
                _port_item port = (_port_item)m_router.m_lstPort1[device.index]; 
                Point2d ptPort = port.pt;

                //第一张图，端口坐标和设备中心坐标x相同
                _polyline_item pl_item = new _polyline_item();
                pl_item.ptList = new ArrayList();
                //第一个点
                pl_item.ptList.Add(new Point2d(ptPort.X, 0));

                if (0 == i)
                {
                    //第二个点
                    pl_item.ptList.Add(new Point2d(ptPort.X, m_disDeviceRouter));
                }
                else
                {
                    //计算 上一个连线的第二个点的 y坐标
                    _polyline_item temp = (_polyline_item)m_lstPolyline1[m_lstPolyline1.Count - 1];
                    Point2d pt = (Point2d)temp.ptList[1];
                    int nY = (int)pt.Y;

                    //point 2
                    pl_item.ptList.Add(new Point2d(ptPort.X, nY - m_disLine));

                    //point 3 
                    pl_item.ptList.Add(new Point2d(device.pt.X + m_nDeviceWidth/2, nY - m_disLine));

                    //point 4 
                    pl_item.ptList.Add(new Point2d(device.pt.X + m_nDeviceWidth / 2, m_disDeviceRouter));
                    

                }

                m_lstPolyline1.Add(pl_item);
            }

            //计算交换机下方连线的位置
            nDeviceCount = m_lstDevice2.Count;
            for (int i = 0; i < nDeviceCount; i++)
            {
                _device_item device = (_device_item)m_lstDevice2[i];
                Point2d ptDevice = device.pt;
                _port_item port = (_port_item)m_router.m_lstPort2[device.index];
                Point2d ptPort = port.pt;

                //第一张图，端口坐标和设备中心坐标x相同
                _polyline_item pl_item = new _polyline_item();
                pl_item.ptList = new ArrayList();
                //第一个点
                pl_item.ptList.Add(new Point2d(ptPort.X, -m_nRouterHeight));

                if (0 == i)
                {
                    //第二个点
                    pl_item.ptList.Add(new Point2d(ptPort.X, -m_nRouterHeight - m_disDeviceRouter));
                }
                else
                {
                    //计算 上一个连线的第二个点的 y坐标
                    _polyline_item temp = (_polyline_item)m_lstPolyline2[m_lstPolyline2.Count - 1];
                    Point2d pt = (Point2d)temp.ptList[1];
                    int nY = (int)pt.Y;

                    //point 2
                    pl_item.ptList.Add(new Point2d(ptPort.X, nY + m_disLine));

                    //point 3 
                    pl_item.ptList.Add(new Point2d(device.pt.X + m_nDeviceWidth / 2, nY + m_disLine));

                    //point 4 
                    pl_item.ptList.Add(new Point2d(device.pt.X + m_nDeviceWidth / 2, -m_nRouterHeight - m_disDeviceRouter));


                }

                m_lstPolyline2.Add(pl_item);

            }


        }

        //画图主入口
        public void DrawZuWang(ArrayList lstRouter)
        {
            //新创建一个dwg文件
            DocumentCollection acDocMgr = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
            Document acDoc = acDocMgr.Add("");
            Database acCurDb = acDoc.Database;
            int nRouterCount = lstRouter.Count;

            if (nRouterCount == 0)
            {
                MessageBox.Show("输入路由列表为空");
            }

            m_router = new _router_item();
            m_router.m_ptOffset = new Point2d(0, 0);
            m_router.m_lstPort1 = new ArrayList();
            m_router.m_lstPort2 = new ArrayList();

            //循环处理每一个路由设备
           // for (int i = 0; i < nRouterCount; i++)
            {
                int nWidth = 0;

                _router router = (_router)lstRouter[0];
                CalLayout(router);


                //画交换机端口图

                //画设备图

                //画poliy图
                
                acDoc.LockDocument();

                // 启动一个事务  Start a transaction
                using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
                {
                    // 以只读方式打开块表   Open the Block table for read
                    BlockTable acBlkTbl;
                    acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
                                                 OpenMode.ForRead) as BlockTable;

                    // 以写方式打开模型空间块表记录   Open the Block table record Model space for write
                    BlockTableRecord acBlkTblRec;
                    acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
                                                    OpenMode.ForWrite) as BlockTableRecord;

                    //画当前交换机图
                    Table tbl = new Table();
                    tbl.TableStyle = acCurDb.Tablestyle;
                    tbl.NumRows = 1;
                    tbl.NumColumns = 1;
                    tbl.Position = m_pOffset + new Vector3d(m_router.m_ptOffset.X, m_router.m_ptOffset.Y,0);

                    // tbl.SetTextHeight(m_fontWeight);
                    tbl.SetColumnWidth(m_nRouterWidth);
                    tbl.SetRowHeight(m_nRouterHeight);
                    tbl.SetTextString(0, 0, router.name);

                    // 添加新对象到块表记录和事务中   Add the new object to the block table record and the transaction
                    acBlkTblRec.AppendEntity(tbl);
                    acTrans.AddNewlyCreatedDBObject(tbl, true);


                    //画端口
                    int nPortCount = m_router.m_lstPort1.Count;
                    for (int j = 0; j < nPortCount; j++)
                    {
                        _port_item item = (_port_item)m_router.m_lstPort1[j];
                        Point3d pt = m_pOffset + new Vector3d(item.pt.X,item.pt.Y,0);
                        Circle cir = new Circle(pt,Vector3d.ZAxis,m_nRadio);

                        acBlkTblRec.AppendEntity(cir);
                        acTrans.AddNewlyCreatedDBObject(cir, true);

                        MText text = new MText();
                        text.Location = pt;
                        text.Contents = item.name;

                        acBlkTblRec.AppendEntity(text);
                        acTrans.AddNewlyCreatedDBObject(text, true);
                    }

                    //画下端口
                    nPortCount = m_router.m_lstPort2.Count;
                    for (int j = 0; j < nPortCount; j++)
                    {
                        _port_item item = (_port_item)m_router.m_lstPort2[j];
                        Point3d pt = m_pOffset + new Vector3d(item.pt.X, item.pt.Y, 0);
                        Circle cir = new Circle(pt, Vector3d.ZAxis, m_nRadio);

                        acBlkTblRec.AppendEntity(cir);
                        acTrans.AddNewlyCreatedDBObject(cir, true);

                        MText text = new MText();
                        text.Location = pt;
                        text.Contents = item.name;

                        acBlkTblRec.AppendEntity(text);
                        acTrans.AddNewlyCreatedDBObject(text, true);
                    }


                    //画设备
                    int nDeviceCount = m_lstDevice1.Count;
                    for (int j = 0; j < nDeviceCount; j++)
                    {
                        _device_item item = (_device_item)m_lstDevice1[j];
                        Point2d pt = item.pt;

                        Table tbl1 = new Table();
                        tbl1.TableStyle = acCurDb.Tablestyle;
                        tbl1.NumRows = 1;
                        tbl1.NumColumns = 1;
                        tbl1.Position = m_pOffset + new Vector3d(pt.X,pt.Y,0);

                        // tbl.SetTextHeight(m_fontWeight);
                        tbl1.SetColumnWidth(m_nDeviceWidth);
                        tbl1.SetRowHeight(m_nDeviceHeight);
                        tbl1.SetTextString(0, 0, item.name);

                        // 添加新对象到块表记录和事务中   Add the new object to the block table record and the transaction
                        acBlkTblRec.AppendEntity(tbl1);
                        acTrans.AddNewlyCreatedDBObject(tbl1, true);


                    }

                    nDeviceCount = m_lstDevice2.Count;
                    for (int j = 0; j < nDeviceCount; j++)
                    {
                        _device_item item = (_device_item)m_lstDevice2[j];
                        Point2d pt = item.pt;

                        Table tbl1 = new Table();
                        tbl1.TableStyle = acCurDb.Tablestyle;
                        tbl1.NumRows = 1;
                        tbl1.NumColumns = 1;
                        tbl1.Position = m_pOffset + new Vector3d(pt.X, pt.Y, 0);

                        // tbl.SetTextHeight(m_fontWeight);
                        tbl1.SetColumnWidth(m_nDeviceWidth);
                        tbl1.SetRowHeight(m_nDeviceHeight);
                        tbl1.SetTextString(0, 0, item.name);

                        // 添加新对象到块表记录和事务中   Add the new object to the block table record and the transaction
                        acBlkTblRec.AppendEntity(tbl1);
                        acTrans.AddNewlyCreatedDBObject(tbl1, true);


                    }

                    //画线
                    for (int index = 0; index < m_lstPolyline1.Count; index++)
                    {
                        _polyline_item item = (_polyline_item)m_lstPolyline1[index];
                        Polyline pl_line = null;
                        if (item.ptList.Count <= 0)
                            continue;

                        pl_line = new Polyline();
                        for (int nPtCount = 0; nPtCount < item.ptList.Count; nPtCount++)
                        {
                            Point2d pt = (Point2d)item.ptList[nPtCount] + new Vector2d(m_pOffset.X, m_pOffset.Y);
                            pl_line.AddVertexAt(nPtCount, pt, 0, 0, 0);
                        }

                        acBlkTblRec.AppendEntity(pl_line);
                        acTrans.AddNewlyCreatedDBObject(pl_line, true);

                    }

                    for (int index = 0; index < m_lstPolyline2.Count; index++)
                    {
                        _polyline_item item = (_polyline_item)m_lstPolyline2[index];
                        Polyline pl_line = null;
                        if (item.ptList.Count <= 0)
                            continue;

                        pl_line = new Polyline();
                        for (int nPtCount = 0; nPtCount < item.ptList.Count; nPtCount++)
                        {
                            Point2d pt = (Point2d)item.ptList[nPtCount] + new Vector2d(m_pOffset.X, m_pOffset.Y);
                            pl_line.AddVertexAt(nPtCount, pt, 0, 0, 0);
                        }

                        acBlkTblRec.AppendEntity(pl_line);
                        acTrans.AddNewlyCreatedDBObject(pl_line, true);

                    }


                    acTrans.Commit();

                }

             //   acCurDb.SaveAs("c:\\1.dwg", DwgVersion.Current);

/*
                //计算当前图纸的最大边距，以计算下一幅幅图的起始位置
                if (m_lstDevice1.Count > m_lstDevice2.Count)
                {
                    _device_item device = (_device_item)m_lstDevice1[m_lstDevice1.Count - 1];
                    nWidth = (int)device.pt.X + m_nDeviceWidth;
                }
                else
                {
                    _device_item device = (_device_item)m_lstDevice2[m_lstDevice2.Count - 1];
                    nWidth = (int)device.pt.X + m_nDeviceWidth;
                }

                //计算设备和路由器边距最大值,以及新路由图的起始点
                if ((m_router.m_ptOffset.X + m_nRouterWidth) > nWidth)
                {
                    nWidth =(int) m_router.m_ptOffset.X + m_nRouterWidth;
                }

                nWidth += m_disRouter;
                m_router.m_ptOffset = new Point2d(nWidth, 0);

                //画完一个交换机设备，清除设备信息，准备下一个
                //交换机图
                m_router.m_lstPort1.Clear();
                m_router.m_lstPort2.Clear();
                m_lstPolyline.Clear();
                m_lstDevice1.Clear();
                m_lstDevice2.Clear();
 * */
            }

        }

    }
}
    